package com.example.demo.redis;

import com.example.demo.services.OrderService;
import com.example.demo.services.impl.OrderServiceImpl;
import com.example.demo.utils.ScriptUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;

@Slf4j
public class RedisLimit {

    private static final int FAIL_CODE = 0;

    private static Integer limit = 5;
    private static final Logger log=  LogManager.getLogger();
    @Autowired
    private OrderServiceImpl orderService;

    private static final String success = "SUCCESS";
    private static final String error = "ERROR";

    /**
     * Redis 限流
     */
    public static Boolean limit() {
        Jedis jedis = null;
        Object result = null;
        try {
            // 获取 jedis 实例
            jedis = RedisPool.getJedis();
            // 解析 Lua 文件
            String script = ScriptUtil.getScript("limit.lua");
            // 请求限流
            String key = String.valueOf(System.currentTimeMillis() / 1000);
            // 计数限流
            result = jedis.eval(script, Collections.singletonList(key), Collections.singletonList(String.valueOf(limit)));
            if (FAIL_CODE != (Long) result) {
                log.info("成功获取令牌");
                return true;
            }
        } catch (Exception e) {
            //log.error(limit, e);
        } finally {
            RedisPool.jedisPoolClose(jedis);
        }
        return false;
    }

    // 在 Controller 中，每个请求到来先取令牌，获取到令牌再执行后续操作，获取不到直接返回 ERROR
//    public String createOptimisticLimitOrder(HttpServletRequest request, int sid) {
//        int res = 0;
//        try {
//            if (RedisLimit.limit()) {
//                res = orderService.createOptimisticOrder(sid);
//            }
//        } catch (Exception e) {
//            //log.error("Exception: " + e);
//        }
//        return res == 1 ? success : error;
//    }
}
